﻿
using System;
using System.IO;
using System.Linq;
using System.Reflection;


namespace Boilen.Primitives.CodeGeneration {

    public sealed class CodeFileWriter : CodeWriter, IDisposable {

        public static readonly string CodeDirectory = GetCodeDirectory( );

        private static string GetCodeDirectory( ) {
            string currentDirectory = Environment.CurrentDirectory;
            string subdirectoryName = typeof( CodeFileWriter ).Namespace.Split( '.' ).Last( );
            string codeDirectory = Path.Combine( currentDirectory, subdirectoryName );
            Directory.CreateDirectory( codeDirectory );
            return codeDirectory;
        }


        private readonly string callerName_;
        private readonly string typeName_;
        private readonly string fileName_;
        private readonly string filePath_;
        private StreamWriter fileWriter_;

        public string CallerName { get { return this.callerName_; } }
        public string TypeName { get { return this.typeName_; } }
        public string FileName { get { return this.fileName_; } }
        public string FilePath { get { return this.filePath_; } }

        private StreamWriter FileWriter {
            get {
                if( this.fileWriter_ == null ) {
                    var fileStream = new FileStream( this.FilePath, FileMode.Create, FileAccess.Write, FileShare.None );
                    this.fileWriter_ = new StreamWriter( fileStream );
                }

                return this.fileWriter_;
            }
        }


        public CodeFileWriter( MethodBase caller, Type type ) {
            char[] invalidCharacters = Path.GetInvalidFileNameChars( );
            this.callerName_ = invalidCharacters.Aggregate( caller.Name, ( s, c ) => s.Replace( c.ToString( ), "" ) );
            this.typeName_ = type.Name.Replace( "`1", "`T" );

            this.fileName_ = this.typeName_ + "__" + this.callerName_ + ".cs";
            this.filePath_ = Path.Combine( CodeDirectory, this.fileName_ );
        }


        public void Dispose( ) {
            if( this.fileWriter_ != null ) {
                this.fileWriter_.Close( );
                this.fileWriter_ = null;
            }
        }


        protected override void WriteCore( string value ) {
            this.FileWriter.Write( value );
        }

        protected override void WriteLineCore( string value ) {
            this.FileWriter.WriteLine( value );
        }

    }

}
